home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 2001 May / SGI Freeware 2001 May - Disc 3.iso / dist / fw_expect.idb / usr / freeware / bin / autoexpect.z / autoexpect
Text File  |  1999-01-26  |  8KB  |  348 lines

  1. #!/usr/freeware/bin/expect --
  2. # Name: autoexpect - generate an Expect script from watching a session
  3. #
  4. # Description:
  5. #
  6. # Given a program name, autoexpect will run that program.  Otherwise
  7. # autoexpect will start a shell.  Interact as desired.  When done, exit
  8. # the program or shell.  Autoexpect will create a script that reproduces
  9. # your interactions.  By default, the script is named script.exp.
  10. # See the man page for more info.
  11. #
  12. # Author: Don Libes, NIST
  13. # Date: June 30 1995
  14. # Version: 1.4b
  15.  
  16. set filename "script.exp"
  17. set verbose 1
  18. set conservative 0
  19. set promptmode 0
  20. set option_keys ""
  21.  
  22. proc check_for_following {type} {
  23.     if ![llength [uplevel set argv]] {
  24.         puts "autoexpect: [uplevel set flag] requires following $type"
  25.         exit 1
  26.     }
  27. }    
  28.  
  29. while {[llength $argv]>0} {
  30.     set flag [lindex $argv 0]
  31.     if 0==[regexp "^-" $flag] break
  32.     set argv [lrange $argv 1 end]
  33.     switch -- $flag \
  34.       "-c" {
  35.         set conservative 1
  36.     } "-C" {
  37.         check_for_following character
  38.         lappend option_keys [lindex $argv 0] ctoggle
  39.         set argv [lrange $argv 1 end]
  40.     } "-p" {
  41.         set promptmode 1
  42.     } "-P" {
  43.         check_for_following character
  44.         lappend option_keys [lindex $argv 0] ptoggle
  45.         set argv [lrange $argv 1 end]
  46.     } "-Q" {
  47.         check_for_following character
  48.         lappend option_keys [lindex $argv 0] quote
  49.         set argv [lrange $argv 1 end]
  50.     } "-f" {
  51.         check_for_following filename
  52.         set filename [lindex $argv 0]
  53.         set argv [lrange $argv 1 end]
  54.     } "-quiet" {
  55.         set verbose 0
  56.     } default {
  57.         break
  58.     }
  59. }
  60.  
  61. #############################################################
  62. # Variables    Descriptions
  63. #############################################################
  64. # userbuf    buffered characters from user
  65. # procbuf    buffered characters from process
  66. # lastkey    last key pressed by user
  67. #        if undefined, last key came from process
  68. # echoing    if the process is echoing
  69. #############################################################
  70.  
  71. # Handle a character that came from user input (i.e., the keyboard)
  72. proc input {c} {
  73.     global userbuf lastkey
  74.  
  75.     send -- $c
  76.     append userbuf $lastkey
  77.     set lastkey $c
  78. }
  79.  
  80. # Handle a null character from the keyboard
  81. proc input_null {} {
  82.     global lastkey userbuf procbuf echoing
  83.  
  84.     send -null
  85.  
  86.     if {$lastkey == ""} {
  87.         if $echoing {
  88.             sendcmd "$userbuf"
  89.         }
  90.         if {$procbuf != ""} {
  91.             expcmd "$procbuf"
  92.         }
  93.     } else {
  94.         sendcmd "$userbuf"
  95.         if $echoing {
  96.             expcmd "$procbuf"
  97.             sendcmd "$lastkey"
  98.         }            
  99.     }
  100.     cmd "send -null"
  101.     set userbuf ""
  102.     set procbuf ""
  103.     set lastkey ""
  104.     set echoing 0
  105. }
  106.  
  107. # Handle a character that came from the process
  108. proc output {s} {
  109.     global lastkey procbuf userbuf echoing
  110.  
  111.     send_user -raw -- $s
  112.  
  113.     if {$lastkey == ""} {
  114.         if !$echoing {
  115.             append procbuf $s
  116.         } else {
  117.             sendcmd "$userbuf"
  118.             expcmd "$procbuf"
  119.             set echoing 0
  120.             set userbuf ""
  121.             set procbuf $s
  122.         }
  123.         return
  124.     }
  125.  
  126.     regexp (.)(.*) $s dummy c tail
  127.     if {$c == $lastkey} {
  128.         if $echoing {
  129.             append userbuf $lastkey
  130.             set lastkey ""
  131.         } else {
  132.             if {$procbuf != ""} {
  133.                 expcmd "$procbuf"
  134.                 set procbuf ""
  135.             }
  136.             set echoing 1
  137.         }
  138.         append procbuf $s
  139.  
  140.         if [string length $tail] {
  141.             sendcmd "$userbuf$lastkey"
  142.             set userbuf ""
  143.             set lastkey ""
  144.             set echoing 0
  145.         }
  146.     } else {
  147.         if !$echoing {
  148.             expcmd "$procbuf"
  149.         }
  150.         sendcmd "$userbuf$lastkey"
  151.         set procbuf $s
  152.         set userbuf ""
  153.         set lastkey ""
  154.         set echoing 0
  155.     }
  156. }
  157.  
  158. # rewrite raw strings so that can appear as source code but still reproduce
  159. # themselves.
  160. proc expand {s} {
  161.     regsub -all "\\\\" $s "\\\\\\\\" s
  162.     regsub -all "\r" $s "\\r"  s
  163.     regsub -all "\"" $s "\\\"" s
  164.     regsub -all "\\\[" $s "\\\[" s
  165.     regsub -all "\\\]" $s "\\\]" s
  166.     regsub -all "\\\$" $s "\\\$" s
  167.  
  168.     return $s
  169. }
  170.  
  171. # generate an expect command
  172. proc expcmd {s} {
  173.     global promptmode
  174.  
  175.     if $promptmode {
  176.         regexp ".*\[\r\n]+(.*)" $s dummy s
  177.     }
  178.  
  179.     cmd "expect -exact \"[expand $s]\""
  180. }
  181.  
  182. # generate a send command
  183. proc sendcmd {s} {
  184.     global send_style conservative
  185.  
  186.     if {$conservative} {
  187.         cmd "sleep .1"
  188.     }
  189.  
  190.     cmd "send$send_style -- \"[expand $s]\""
  191. }
  192.  
  193. # generate any command
  194. proc cmd {s} {
  195.     global fd
  196.     puts $fd "$s"
  197. }
  198.  
  199. proc verbose_send_user {s} {
  200.     global verbose
  201.  
  202.     if $verbose {
  203.         send_user -- $s
  204.     }
  205. }
  206.  
  207. proc ctoggle {} {
  208.     global conservative send_style
  209.  
  210.     if $conservative {
  211.         cmd "# conservative mode off - adding no delays"
  212.         verbose_send_user "conservative mode off\n"
  213.         set conservative 0
  214.         set send_style ""
  215.     } else {
  216.         cmd "# prompt mode on - adding delays"
  217.         verbose_send_user "conservative mode on\n"
  218.         set conservative 1
  219.         set send_style " -s"
  220.     }
  221. }
  222.  
  223. proc ptoggle {} {
  224.     global promptmode
  225.  
  226.     if $promptmode {
  227.         cmd "# prompt mode off - now looking for complete output"
  228.         verbose_send_user "prompt mode off\n"
  229.         set promptmode 0
  230.     } else {
  231.         cmd "# prompt mode on - now looking only for prompts"
  232.         verbose_send_user "prompt mode on\n"
  233.         set promptmode 1
  234.     }
  235. }
  236.  
  237. # quote the next character from the user
  238. proc quote {} {
  239.     expect_user -re .
  240.     send -- $expect_out(buffer)
  241. }
  242.     
  243.  
  244. if [catch {set fd [open $filename w]} msg] {
  245.     puts $msg
  246.     exit
  247. }
  248. exec chmod +x $filename
  249. verbose_send_user "autoexpect started, file is $filename\n"
  250.  
  251. # calculate a reasonable #! line
  252. set expectpath /usr/local/bin        ;# prepare default
  253. foreach dir [split $env(PATH) :] {    ;# now look for real location
  254.     if [file executable $dir/expect] {
  255.         set expectpath $dir
  256.         break
  257.     }
  258. }
  259.  
  260. cmd "#![set expectpath]/expect -f
  261. #
  262. # This Expect script was generated by autoexpect on [timestamp -format %c]
  263. # Expect and autoexpect were both written by Don Libes, NIST."
  264. cmd {#
  265. # Note that autoexpect does not guarantee a working script.  It
  266. # necessarily has to guess about certain things.  Two reasons a script
  267. # might fail are:
  268. #
  269. # 1) timing - A surprising number of programs (rn, ksh, zsh, telnet,
  270. # etc.) and devices discard or ignore keystrokes that arrive "too
  271. # quickly" after prompts.  If you find your new script hanging up at
  272. # one spot, try adding a short sleep just before the previous send.
  273. # Setting "force_conservative" to 1 (see below) makes Expect do this
  274. # automatically - pausing briefly before sending each character.  This
  275. # pacifies every program I know of.  The -c flag makes the script do
  276. # this in the first place.  The -C flag allows you to define a
  277. # character to toggle this mode off and on.
  278.  
  279. set force_conservative 0  ;# set to 1 to force conservative mode even if
  280.               ;# script wasn't run conservatively originally
  281. if {$force_conservative} {
  282.     set send_slow {1 .1}
  283.     proc send {ignore arg} {
  284.         sleep .1
  285.         exp_send -s -- $arg
  286.     }
  287. }
  288.  
  289. #
  290. # 2) differing output - Some programs produce different output each time
  291. # they run.  The "date" command is an obvious example.  Another is
  292. # ftp, if it produces throughput statistics at the end of a file
  293. # transfer.  If this causes a problem, delete these patterns or replace
  294. # them with wildcards.  An alternative is to use the -p flag (for
  295. # "prompt") which makes Expect only look for the last line of output
  296. # (i.e., the prompt).  The -P flag allows you to define a character to
  297. # toggle this mode off and on.
  298. #
  299. # Read the man page for more info.
  300. #
  301. # -Don
  302.  
  303. }
  304.  
  305. cmd "set timeout -1"
  306. if $conservative {
  307.     set send_style " -s"
  308.     cmd "set send_slow {1 .1}"
  309. } else {
  310.     set send_style ""
  311. }
  312.  
  313. if [llength $argv]>0 {
  314.     eval spawn -noecho $argv
  315.     cmd "spawn $argv"
  316. } else {
  317.     spawn -noecho $env(SHELL)
  318.     cmd "spawn \$env(SHELL)"
  319. }
  320.  
  321. cmd "match_max 100000"
  322.  
  323. set lastkey ""
  324. set procbuf ""
  325. set userbuf ""
  326. set echoing 0
  327.  
  328. remove_nulls 0
  329.  
  330. eval interact $option_keys {
  331.     -re . {
  332.         input $interact_out(0,string)
  333.     } null {
  334.         input_null
  335.     } \
  336.     -o \
  337.     -re .+ {
  338.         output $interact_out(0,string)
  339.     } eof {
  340.         cmd "expect eof"
  341.         return
  342.     } null {
  343.     }
  344. }
  345.  
  346. close $fd
  347. verbose_send_user "autoexpect done, file is $filename\n"
  348.